home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl1 / answers / blending.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  22.3 KB  |  908 lines

  1. /*
  2.  * Copyright 1996, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /* blending.c - open a window and clear the background.
  19.  *    Set up callbacks to handle keyboard input.
  20.  *      Model some objects.  Use perspective projection.
  21.  *    Use independent modeling transformations to position objects.
  22.  *    Added reshape callback to reset the viewport and viewing volume.
  23.  *    Add depth buffering.
  24.  *    Add a viewing transformation and control it using mouse input.
  25.  *    Add continuous animation and a menu to control it.
  26.  *    Add a local light with distance attenuation, and a spot light.
  27.  *    Add two-sided lighting, and a back face material for one object.
  28.  *    Add 3D text.
  29.  *    Add display lists.
  30.  *    Add alpha blending and antialising.
  31.  *
  32.  *    F1 key            - print help information
  33.  *    Right Mouse Button    - popup menu
  34.  *    Left Arrow Key        - move the reference point to the left
  35.  *    Right Arrow Key        - move the reference point to the right
  36.  *    Up Arrow Key        - move the reference point up
  37.  *    Down Arrow Key        - move the reference point down
  38.  *    <b> key            - toggle between bitmap/stroke fonts
  39.  *    <e> key            - cycle through different blend equations
  40.  *    <f> key            - toggle front/back face culling
  41.  *    <n> key            - toggle between night/day
  42.  *    <s> key            - toggle smooth/flat shading
  43.  *    SPACE key        - generates a random background color
  44.  *    Escape Key        - exit program
  45.  */
  46. #include <GL/gl.h>
  47. #include <GL/glu.h>
  48. #include <GL/glut.h>
  49.  
  50. #include <stdio.h>
  51. #include <math.h>
  52.  
  53. #include "fonts.h"    /* contains descriptions for 3 sample fonts */
  54.  
  55. /* Function Prototypes */
  56.  
  57. GLvoid initgfx( GLvoid );
  58. GLvoid keyboard( GLubyte, GLint, GLint );
  59. GLvoid specialkeys( GLint, GLint, GLint );
  60. GLvoid reshape( GLsizei, GLsizei );
  61. GLvoid animate( GLvoid );
  62. GLvoid visibility( GLint );
  63. GLvoid drawScene( GLvoid );
  64. GLvoid menuFunc( GLint );
  65.  
  66. void initGround( GLvoid );
  67. GLvoid drawGround( GLvoid );
  68. GLuint  create3DFont( GLfloat font[][1+MAX_STROKES*3] );
  69.  
  70. void checkError( char * );
  71. void printHelp( char * );
  72.  
  73. /* Global Variables */
  74.  
  75. static GLdouble        xRef = 0.0, yRef = 0.0;
  76.  
  77. static GLfloat        sunPosition = 2.5;
  78. static GLboolean    night = GL_FALSE;
  79. static GLboolean    use_bitmap_fonts = GL_FALSE;
  80.  
  81. static GLfloat         green[] = { 0.0, 1.0, 0.0 };
  82. static GLfloat         darkgreen[] = { 0.0, 0.25, 0.0 };
  83. static GLfloat         red[] = { 1.0, 0.0, 0.0 };
  84. static GLfloat         magenta[] = { 1.0, 0.0, 1.0 };
  85. static GLfloat         yellow[] = { 1.0, 1.0, 0.0 };
  86. static GLfloat         blue[] = { 0.0, 0.0, 1.0 };
  87.  
  88. static GLfloat         white[] = { 1.0, 1.0, 1.0, 1.0 };
  89. static GLfloat         black[] = { 0.0, 0.0, 0.0, 0.0 };
  90.  
  91. static void           *fixedFont, *romanFont;
  92.  
  93. static GLuint        groundList;
  94. static GLuint         outlineBase;
  95.  
  96. static char *progname; 
  97.  
  98. /* Global Definitions */
  99.  
  100. #define KEY_ESC    27    /* ascii value for the escape key */
  101.  
  102. /* menu options */
  103. #define MENU_ANIMATE    1    /* animation control option */
  104. #define MENU_EXIT    2    /* exit option */
  105.  
  106. #define GRIDPOINTS    41    /* number of vertices in ground mesh */
  107.  
  108. static GLfloat         groundMesh[GRIDPOINTS][GRIDPOINTS][3] = { 0 };
  109.  
  110. static GLboolean     animateFlag = GL_TRUE;
  111.  
  112. void
  113. main( int argc, char *argv[] )
  114. {
  115.     GLsizei width, height;
  116.  
  117.     glutInit( &argc, argv );
  118.  
  119.     /* create a window that is 1/4 the size of the screen,
  120.      * and position it in the middle of the screen.
  121.      */
  122.     width = glutGet( GLUT_SCREEN_WIDTH ); 
  123.     height = glutGet( GLUT_SCREEN_HEIGHT );
  124.     glutInitWindowPosition( width / 4, height / 4 );
  125.     glutInitWindowSize( width / 2, height / 2 );
  126.     glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
  127.     glutCreateWindow( argv[0] );
  128.  
  129.     initgfx();
  130.  
  131.     glutIdleFunc( animate );
  132.     glutVisibilityFunc( visibility );
  133.     glutReshapeFunc( reshape );
  134.     glutKeyboardFunc( keyboard );
  135.     glutSpecialFunc( specialkeys );
  136.     glutDisplayFunc( drawScene ); 
  137.  
  138.     /* create menu and add menu options */
  139.     glutCreateMenu( menuFunc );
  140.     glutAddMenuEntry( "Stop Animation", MENU_ANIMATE );
  141.     glutAddMenuEntry( "Exit", MENU_EXIT );
  142.     glutAttachMenu( GLUT_RIGHT_BUTTON );
  143.  
  144.     progname = argv[0];
  145.  
  146.     printHelp( progname );
  147.  
  148.     glutMainLoop();
  149. }
  150.  
  151. void
  152. printHelp( char *progname )
  153. {
  154.     fprintf(stdout, 
  155.         "\n%s - create a scene using display lists\n\n"
  156.         "F1 key        - print help information\n"
  157.         "Left Arrow Key        - move reference point to the left\n"
  158.         "Right Arrow Key    - move reference point to the right\n"
  159.         "Up Arrow Key        - move reference point up\n"
  160.         "Down Arrow Key        - move reference point down\n"
  161.         "SPACE Key    - generates a random background color\n"
  162.         "<b> key    - toggle between bitmap/stroke fonts\n"
  163.          "<e> key    - cycle through different blend equations\n"
  164.         "<f> key        - toggle front/back face culling\n"
  165.         "<n> key        - toggle between night/day\n"
  166.         "<s> key        - toggle smooth/flat shading\n"
  167.         "Escape Key    - exit the program\n\n",
  168.         progname);
  169. }
  170.  
  171. GLvoid
  172. initgfx( GLvoid )
  173. {
  174.     char *extName1 = "GL_EXT_blend_subtract";
  175.     char *extName2 = "GL_EXT_blend_minmax";
  176.     char *extName3 = "GL_EXT_blend_logic_op";
  177.  
  178.     GLfloat sunAmbient[4] = { 0.5, 0.5, 0.5, 1.0 };
  179.  
  180.     /* set clear color to blue */
  181.     glClearColor( 0.0, 0.0, 1.0, 1.0 );
  182.  
  183.     /* enable the depth buffer */
  184.     glEnable( GL_DEPTH_TEST );
  185.  
  186.     /* enable the face culling */
  187.     glEnable( GL_CULL_FACE );
  188.  
  189.     initGround();
  190.  
  191.     glMaterialfv( GL_BACK, GL_AMBIENT_AND_DIFFUSE, yellow );
  192.  
  193.     glMaterialfv( GL_FRONT, GL_SPECULAR, white );
  194.     glMaterialf( GL_FRONT, GL_SHININESS, 10.0 );
  195.  
  196.     /* Add a light for the sun */
  197.     glLightfv( GL_LIGHT0, GL_DIFFUSE, white );
  198.     glLightfv( GL_LIGHT0, GL_AMBIENT, sunAmbient );
  199.     glEnable( GL_LIGHT0 );
  200.     glEnable( GL_LIGHTING );
  201.  
  202.     /* have OpenGL automatically normalize the normals,
  203.      * since we have lighting turned on and are scaling
  204.       */
  205.     glEnable( GL_NORMALIZE );
  206.  
  207.     /* Enable fast material changes for diffuse material */
  208.     glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
  209.     glEnable( GL_COLOR_MATERIAL );
  210.  
  211.     /* Set up two fonts to use for rendering */
  212.     fixedFont = GLUT_BITMAP_9_BY_15;
  213.     romanFont = GLUT_STROKE_ROMAN;
  214.  
  215.     groundList = glGenLists(1);
  216.     glNewList( groundList, GL_COMPILE );
  217.         drawGround();
  218.     glEndList();
  219.  
  220.     outlineBase = create3DFont( outlineFont );
  221.  
  222.     /* Make sure new blend_* extensions exist */
  223.     if (glutExtensionSupported(extName1) == 0) {
  224.         printf("%s is not supported by the server.\n", extName1);
  225.     }
  226.     if (glutExtensionSupported(extName2) == 0) {
  227.         printf("%s is not supported by the server.\n", extName2);
  228.     }
  229.     if (glutExtensionSupported(extName3) == 0) {
  230.         printf("%s is not supported by the server.\n", extName3);
  231.     }
  232.  
  233.     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  234.     fprintf(stdout, 
  235.         "glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA )\n");
  236. }
  237.  
  238. GLvoid 
  239. reshape( GLsizei width, GLsizei height )
  240. {
  241.     GLdouble    aspect;
  242.  
  243.     glViewport( 0, 0, width, height );
  244.  
  245.     /* compute aspect ratio */
  246.     aspect = (GLdouble) width / (GLdouble) height;
  247.  
  248.     glMatrixMode( GL_PROJECTION );
  249.  
  250.     /* Reset world coordinates first ... */
  251.     glLoadIdentity();
  252.  
  253.     /* Reset the viewing volume based on the new aspect ratio */
  254.     gluPerspective( 45.0, aspect, 3.0, 7.0 );
  255.  
  256.     glMatrixMode( GL_MODELVIEW );
  257. }
  258.  
  259. void 
  260. checkError( char *label )
  261. {
  262.     GLenum error;
  263.     while ( (error = glGetError()) != GL_NO_ERROR )
  264.         printf( "%s: %s\n", label, gluErrorString(error) );
  265. }
  266.  
  267. GLvoid  
  268. cycleBlendEquation( GLvoid )
  269. {
  270.     static int whichBlendEq = 0;
  271.     
  272.     whichBlendEq = (whichBlendEq + 1) % 4;
  273.     
  274.     switch (whichBlendEq)
  275.     {
  276.     case 0:
  277.         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
  278. #ifdef GL_EXT_blend_minmax
  279.         glBlendEquationEXT( GL_FUNC_ADD_EXT );
  280.         fprintf(stdout, "glBlendEquationEXT( GL_FUNC_ADD_EXT )\n");
  281. #endif
  282.         break;
  283.     case 1:
  284. #ifdef GL_EXT_blend_minmax
  285.         glBlendEquationEXT( GL_MIN_EXT );
  286.         fprintf(stdout, "glBlendEquationEXT( GL_MIN_EXT )\n" );
  287. #endif
  288.         break;
  289.     case 2:
  290.         glBlendFunc( GL_ONE, GL_ONE );
  291. #ifdef GL_EXT_blend_subtract
  292.         glBlendEquationEXT( GL_FUNC_REVERSE_SUBTRACT_EXT );
  293.         fprintf(stdout, 
  294.             "glBlendEquationEXT( GL_FUNC_REVERSE_SUBTRACT_EXT )\n");
  295. #endif
  296.         break;
  297.     case 3:
  298. #ifdef GL_EXT_blend_logic_op
  299.         glBlendEquationEXT( GL_LOGIC_OP );
  300.         glLogicOp( GL_XOR );
  301.         fprintf(stdout, "glBlendEquationEXT( GL_LOGIC_OP )\n" );
  302.         fprintf(stdout, "glLogicOp( GL_XOR )\n" );
  303. #endif
  304.         break;
  305.     default:
  306.         break;
  307.     }
  308. }
  309.  
  310. GLvoid 
  311. keyboard( GLubyte key, GLint x, GLint y )
  312. {
  313.     static GLboolean flat = GL_FALSE;
  314.     static GLboolean cullFront = GL_FALSE;
  315.  
  316.     switch (key) {
  317.     case ' ':    /* SPACE key */
  318.         /* generate a random background color */
  319.         glClearColor( drand48(), drand48(), drand48(), 1.0 ); 
  320.         glutPostRedisplay();
  321.         break;
  322.     case 'b':    /* b key */
  323.         /* toggle between bitmap and stroke fonts */
  324.         use_bitmap_fonts = !use_bitmap_fonts;
  325.         break;
  326.     case 'e':    /* e key */
  327.         /* toggle between back and front face culling */
  328.         cycleBlendEquation();
  329.         glutPostRedisplay();
  330.         break;
  331.     case 'f':    /* f key */
  332.         /* toggle between back and front face culling */
  333.         cullFront = !cullFront;
  334.         if (cullFront) {
  335.             glCullFace( GL_FRONT );
  336.             printf("Culling FRONT faces\n");
  337.         } else { 
  338.             glCullFace( GL_BACK );
  339.             printf("Culling BACK faces\n");
  340.         }
  341.         glutPostRedisplay();
  342.         break;
  343.     case 'n':    /* n key */
  344.         /* toggle between night and day */
  345.         night = !night;
  346.         if (night) {
  347.             /* make the light fall off with distance much
  348.              * more quickly when it is night 
  349.              */
  350.             glLightf( GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.1 );
  351.         } else { 
  352.             glLightf( GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0 );
  353.         }
  354.         glutPostRedisplay();
  355.         break;
  356.     case 's':    /* s key */
  357.         /* toggle between smooth and flat shading */
  358.         flat = !flat;
  359.         if (flat)
  360.             glShadeModel( GL_FLAT );
  361.         else 
  362.             glShadeModel( GL_SMOOTH );
  363.         glutPostRedisplay();
  364.         break;
  365.     case KEY_ESC:    /* Exit when the Escape key is pressed */
  366.         exit(0);
  367.     }
  368. }
  369.  
  370. GLvoid 
  371. specialkeys( GLint key, GLint x, GLint y )
  372. {
  373.     switch (key) {
  374.     case GLUT_KEY_F1:    /* Function key #1 */
  375.         /* print help information */
  376.         printHelp( progname );
  377.         break;
  378.  
  379.     case GLUT_KEY_LEFT:    /* move reference point to the left */
  380.         xRef -= 0.5;
  381.         if (xRef < -4.0) xRef = -4.0;
  382.         glutPostRedisplay();
  383.          break;
  384.  
  385.     case GLUT_KEY_RIGHT:    /* move reference point to the right */
  386.         xRef += 0.5;
  387.         if (xRef > 4.0) xRef = 4.0;
  388.         glutPostRedisplay();
  389.         break;
  390.  
  391.     case GLUT_KEY_UP:    /* move reference point up */
  392.         yRef += 0.5;
  393.         if (yRef > 3.0) yRef = 3.0;
  394.         glutPostRedisplay();
  395.         break;
  396.  
  397.     case GLUT_KEY_DOWN:    /* move reference point down */
  398.         yRef -= 0.5;
  399.         if (yRef < -3.0) yRef = -3.0;
  400.         glutPostRedisplay();
  401.         break;
  402.     }
  403. }
  404.  
  405. GLvoid 
  406. animate( GLvoid )
  407. {
  408.     /* update the position of the sun */
  409.     sunPosition -= 0.01;
  410.     if (sunPosition < -3.0) sunPosition = 2.5;
  411.  
  412.     /* Tell GLUT to redraw the scene */
  413.     glutPostRedisplay();
  414. }
  415.  
  416. GLvoid
  417. visibility( int state ) 
  418. {
  419.     if (state == GLUT_VISIBLE && animateFlag) {
  420.         glutIdleFunc( animate );
  421.     } else {
  422.         glutIdleFunc( NULL );
  423.     }
  424. }
  425.  
  426. GLvoid
  427. menuFunc( int value )
  428. {
  429.     switch (value) {
  430.     case MENU_ANIMATE:
  431.         animateFlag = !animateFlag;
  432.         if (animateFlag) {
  433.             glutIdleFunc( animate );
  434.             glutChangeToMenuEntry( MENU_ANIMATE, "Stop Animation",
  435.                         MENU_ANIMATE );
  436.         } else {
  437.             glutIdleFunc( NULL );
  438.             glutChangeToMenuEntry( MENU_ANIMATE, "Start Animation",
  439.                         MENU_ANIMATE );
  440.         }
  441.         break;
  442.     case MENU_EXIT:
  443.         exit(0);
  444.     }
  445. }
  446.  
  447. void
  448. initGround( void )
  449. {
  450.     int i, j;
  451.     GLfloat     x, y, spacing;
  452.  
  453.     /* Create a flat grid composed of points with the z value = 0 */
  454.     
  455.     /* spacing = distance between adjacent grid points in x and y */
  456.     spacing = 2.0 / (float)(GRIDPOINTS - 1);
  457.  
  458.     /* x and z range from -1.0 to 1.0 by spacing interval */
  459.     for ( x = -1.0, i = 0; i < GRIDPOINTS; x += spacing, i++ ) {
  460.         for ( y = -1.0, j = 0; j < GRIDPOINTS; y += spacing, j++ ) {
  461.             groundMesh[i][j][0] = x;
  462.             groundMesh[i][j][1] = y;
  463.             groundMesh[i][j][2] = 0.0;
  464.         }
  465.     }
  466. }
  467.  
  468. GLvoid
  469. drawGround( GLvoid )
  470. {
  471.     register int i, j;
  472.  
  473.     glNormal3f( 0.0, 0.0, 1.0 );
  474.     
  475.     /* Draw quad strips connecting grid points. 
  476.      * Grid is drawn column by column, 
  477.      * where each column is one quad strip.
  478.      * Every pair of vertices after first two vertices
  479.      * adds a new quad to the strip.
  480.      */
  481.     for ( i = 0; i < (GRIDPOINTS - 1); i++ ) {
  482.         glBegin( GL_QUAD_STRIP );
  483.         for ( j = 0; j < (GRIDPOINTS); j++ ) {
  484.             glColor3f( 0.0, 1.0 - (GLfloat) j/GRIDPOINTS, 0.0 );
  485.             glVertex3fv( &groundMesh[i][j][0] );
  486.             glVertex3fv( &groundMesh[i + 1][j][0] );
  487.         }
  488.         glEnd();
  489.     }
  490. }
  491.  
  492. GLvoid
  493. drawWindow()
  494. {
  495.     /* window */
  496.     static GLfloat v0[] = { 0.0, 0.4 };
  497.     static GLfloat v1[] = { 0.0, 0.0 };
  498.     static GLfloat v2[] = { 0.1, 0.4 };
  499.     static GLfloat v3[] = { 0.1, 0.0 };
  500.     static GLfloat v4[] = { 0.2, 0.4 };
  501.     static GLfloat v5[] = { 0.2, 0.0 };
  502.  
  503.     /* draw an object behind the window */
  504.     glColor4f( 0.2, 0.2, 0.2, 1.0 );
  505.     glPushMatrix();
  506.         glTranslatef( 0.1, 0.1, 0.0 );
  507.         glScalef( 0.5, 1.0, 0.00001 );
  508.         glutSolidTeapot( 0.1 );
  509.     glPopMatrix();
  510.  
  511.     if (!night) {
  512.         /* make the window see through */
  513.         glEnable( GL_BLEND );
  514.  
  515.         /* make sure the depth buffer doesn't remove the teapot */
  516.         glDepthMask( GL_FALSE );
  517.     }
  518.  
  519.     glTranslatef( 0.0, 0.0, 0.00001 );
  520.     /* draw 2 quadrilateral strip to make a window */
  521.     glNormal3f( 0.0, 0.0, 1.0 );
  522.     glBegin( GL_QUAD_STRIP );
  523.         glColor4f( 1.0, 0.0, 0.0, 0.5 );
  524.         glVertex2fv (v0);
  525.         glColor4f( 0.9, 0.0, 1.0, 0.5 );
  526.         glVertex2fv (v1);
  527.         glColor4f( 0.8, 0.1, 0.0, 0.5 );
  528.         glVertex2fv (v2);
  529.         glColor4f( 0.7, 0.2, 1.0, 0.5 );
  530.         glVertex2fv (v3);
  531.         glColor4f( 0.6, 0.3, 0.0, 0.5 );
  532.         glVertex2fv (v4);
  533.         glColor4f( 0.5, 0.4, 1.0, 0.5 );
  534.         glVertex2fv (v5);
  535.         glColor4f( 0.4, 0.5, 0.0, 0.5 );
  536.     glEnd();
  537.  
  538.     if (!night) {
  539.         glDepthMask( GL_TRUE );
  540.         glDisable( GL_BLEND );
  541.     }
  542. }
  543.  
  544. /* draw a "circle" using a triangle fan; set the
  545.  * center of the circle to white, and the outside
  546.  * to the color passed in
  547.  */
  548. GLvoid
  549. drawFan( GLfloat *color )
  550. {
  551.     /* Draw a triangle fan centered at the current coordinate
  552.      * system origin 
  553.      */
  554.     glNormal3f( 0.0, 0.0, 1.0 );
  555.     glBegin( GL_TRIANGLE_FAN );
  556.         glColor3f( 1.0, 1.0, 1.0 );
  557.         glVertex2f( 0.0, 0.0 );
  558.         glColor3fv( color );
  559.         glVertex2f( 0.0, -0.2 );
  560.         glVertex2f( 0.2, -0.1 );
  561.         glVertex2f( 0.2, 0.1 );
  562.         glVertex2f( 0.0, 0.2 );
  563.         glVertex2f( -0.2, 0.1 );
  564.         glVertex2f( -0.2, -0.1 );
  565.         glVertex2f( 0.0, -0.2 );
  566.     glEnd();
  567. }
  568.  
  569. /* draw a flower with the base of the stem 
  570.  * at the current location 
  571.  */
  572. GLvoid
  573. drawFlower( GLfloat *color )
  574. {
  575.     /* draw the stem with 2 leaves */
  576.     glColor3fv( darkgreen );
  577.     glNormal3f( 0.0, 0.0, 1.0 );
  578.     glBegin( GL_LINES );
  579.         glVertex2f( 0.0, 0.0 );         /* stem */
  580.         glVertex2f( 0.0, 0.25 );
  581.         glVertex2f( 0.0, 0.1 );         /* leaf */
  582.         glVertex2f( 0.05, 0.15 ); 
  583.         glVertex2f( 0.0, 0.05 );     /* leaf */
  584.         glVertex2f( -0.05, 0.2 );
  585.     glEnd();
  586.  
  587.     glPushMatrix();
  588.         /* move to the top of the stem */
  589.         glTranslatef( 0.0, 0.25, 0.0 );
  590.  
  591.         /* use a scaled triangle fan for the flower head */
  592.         glScalef( 0.1, 0.1, 1.0 );
  593.         drawFan( color );  
  594.     glPopMatrix();
  595. }
  596.  
  597. /* draw a house centered at the current origin;
  598.  * the bounding box for the house is 1.0 x 2.0 units
  599.  */
  600. GLvoid
  601. drawHouse()
  602. {
  603.     /* draw a 3D house */
  604.     glColor3f( 1.0, 1.0, 1.0 ); /* white */
  605.     SolidBox( 1.0, 1.5, 1.0 );
  606.  
  607.     glPushMatrix();
  608.         /* move to the peak of the roof */
  609.         glTranslatef( 0.0, 1.25, 0.0 );
  610.  
  611.         /* draw a triangle fan for the roof */
  612.         glColor3f( 0.0, 0.0, 0.0 ); /* black */
  613.         glNormal3f( 0.0, 1.0, 1.0 );
  614.         glBegin( GL_TRIANGLE_FAN );
  615.             glVertex3f( 0.0, 0.0, 0.0 ); /* peak */
  616.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  617.             glVertex3f( 0.5, -0.5, 0.5 ); /* front right */
  618.             glVertex3f( 0.5, -0.5, -0.5 ); /* back right */
  619.             glVertex3f( -0.5, -0.5, -0.5 ); /* back left */
  620.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  621.         glEnd();
  622.     glPopMatrix();
  623.  
  624.     glPushMatrix();
  625.         /* move to just in front of the house */
  626.         glTranslatef( 0.0, 0.0, 0.50001 );
  627.  
  628.         /* draw the door */
  629.         glColor3f( 0.5, 0.2, 0.1 ); /* brown */
  630.         glNormal3f( 0.0, 0.0, 1.0 );
  631.         glRectf( -0.2, -0.75, 0.2, 0.0 );
  632.  
  633.         glPushMatrix();
  634.             /* move to the location for the left window */
  635.             glTranslatef( -0.4, 0.2, 0.0 );
  636.             drawWindow();
  637.         glPopMatrix();
  638.  
  639.         glPushMatrix();
  640.             /* move to the location for the right window */
  641.             glTranslatef( 0.2, 0.2, 0.0 );
  642.             drawWindow();
  643.         glPopMatrix();
  644.     glPopMatrix();
  645. }
  646.  
  647. /* draw a lamp post centered at the current origin;
  648.  * the bounding box for the lamp is 0.5 x 3.0 units
  649.  */
  650. GLvoid
  651. drawLamp( GLint light )
  652. {
  653.     GLfloat spot_color[] = { 1.0, 1.0, 0.0, 1.0 };
  654.  
  655.     GLfloat spot_dir[] = { 0.0, 0.0, -1.0 };
  656.     GLfloat spot_cutoff = 30.0;
  657.     GLfloat spot_exp = 20.0;
  658.  
  659.     /* Note that a spotlight is a local light */
  660.     GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 };
  661.  
  662.     /* draw lamp post */
  663.     glColor3f( 0.0, 0.0, 0.0 );
  664.     SolidCylinder( 0.05, 3.0 );
  665.  
  666.     glPushMatrix();
  667.         glTranslatef( 0.0, 1.5, 0.0 );
  668.         glRotatef( -90, 0.0, 0.0, 1.0 );
  669.         glTranslatef( 0.0, 0.25, 0.0 );
  670.         SolidCylinder( 0.02, 0.5 );
  671.  
  672.         glTranslatef( 0.0, 0.2, 0.0 );
  673.         glRotatef( -90.0, 0.0, 1.0, 0.0 );
  674.         glTranslatef( 0.0, 0.0, -0.1 );
  675.         glutSolidCone( 0.05, 0.1, 15, 15 );
  676.  
  677.         if ( night ) { /* turn on the lamp */
  678.             glLightfv( light, GL_DIFFUSE, spot_color );
  679.             glLightfv( light, GL_SPECULAR, spot_color );
  680.             glLightfv( light, GL_SPOT_DIRECTION, spot_dir );
  681.             glLightf( light, GL_SPOT_CUTOFF, spot_cutoff );
  682.             glLightf( light, GL_SPOT_EXPONENT, spot_exp );
  683.             glLightfv( light, GL_POSITION, light_position );
  684.  
  685.             glEnable( light );
  686.         } else
  687.             glDisable( light );
  688.     glPopMatrix();
  689.  
  690. }
  691.  
  692. GLvoid
  693. renderBitmapString( void *font, char *string )
  694. {
  695.         int i;
  696.         int len = (int) strlen(string);
  697.         for (i = 0; i < len; i++) {
  698.                 glutBitmapCharacter(font, string[i]);
  699.         }
  700. }
  701.  
  702. GLvoid
  703. renderStrokeString( void *font, char *string )
  704. {
  705.         int i;
  706.         int len = (int) strlen(string);
  707.         for (i = 0; i < len; i++) {
  708.                 glutStrokeCharacter(font, string[i]);
  709.         }
  710. }
  711.  
  712. GLvoid
  713. render3DString( GLuint fontBase, char *string )
  714. {
  715.     glPushAttrib(GL_LIST_BIT);
  716.         glListBase( fontBase );
  717.         glCallLists( strlen(string), GL_UNSIGNED_BYTE, 
  718.                 (unsigned char *) string );
  719.     glPopAttrib();
  720. }
  721.  
  722. /* Create a display list for each letter in the font description
  723.  * passed in.
  724.  */
  725. GLuint 
  726. create3DFont( GLfloat font[][1+MAX_STROKES*3] )
  727. {
  728.     GLint mode, i, j;
  729.     GLuint fontBase;
  730.     GLfloat fontScale;
  731.  
  732.     fontBase = glGenLists( 256 );
  733.     for (i = 0; font[i][0] != END_OF_LIST; i++) {
  734.         glNewList( fontBase+(GLuint)font[i][0], GL_COMPILE );
  735.         for (j = 1; mode = font[i][j]; j += 3) {
  736.             if (mode == FONT_BEGIN) {
  737.                 fontScale = font[i][j+2];
  738.                 glBegin( (GLint) font[i][j+1] );
  739.             } else if (mode == FONT_NEXT) {
  740.                 glVertex2f( font[i][j+1]*fontScale, 
  741.                         font[i][j+2]*fontScale );
  742.             } else if (mode == FONT_END) {
  743.                 glVertex2f( font[i][j+1]*fontScale, 
  744.                         font[i][j+2]*fontScale );
  745.                 glEnd();
  746.             } else if (mode == FONT_ADVANCE) {
  747.                 glTranslatef( font[i][j+1]*fontScale, 
  748.                           font[i][j+2]*fontScale, 0.0 );
  749.             }
  750.         }
  751.         glEndList();
  752.     }
  753.     return fontBase;
  754. }
  755.  
  756. void
  757. drawSign( GLvoid )
  758. {
  759.     /* draw sign post */
  760.     glColor3f( 0.0, 0.0, 0.0 );
  761.     SolidCylinder( 0.01, 0.5 );
  762.  
  763.     /* draw sign */
  764.     glPushMatrix();
  765.         glTranslatef( 0.0, 0.25, 0.01 );
  766.         glColor3f( 1.0, 1.0, 1.0 );
  767.         glRectf( -0.11, -0.11, 0.11, 0.11 );
  768.  
  769.         glColor3f( 0.0, 0.0, 0.0 );
  770.         if (use_bitmap_fonts) {
  771.             glRasterPos3f( -0.1, 0.04, 0.01 );
  772.             renderBitmapString( fixedFont, "Beware" );
  773.             glRasterPos3f( -0.03, -0.02, 0.01 );
  774.             renderBitmapString( fixedFont, "of" );
  775.             glRasterPos3f( -0.06, -0.08, 0.01 );
  776.             renderBitmapString( fixedFont, "Dog" );
  777.         } else {
  778.             glPushMatrix();
  779.                 glTranslatef( -0.1, 0.04, 0.01 );
  780.                 glScalef( 0.0005, 0.0005, 0.0005 );
  781.                 renderStrokeString( romanFont, "Beware" );
  782.             glPopMatrix();
  783.             glPushMatrix();
  784.                 glTranslatef( -0.03, -0.02, 0.01 );
  785.                 glScalef( 0.0005, 0.0005, 0.0005 );
  786.                 renderStrokeString( romanFont, "of" );
  787.             glPopMatrix();
  788.             glPushMatrix();
  789.                 glTranslatef( -0.06, -0.08, 0.01 );
  790.                 glScalef( 0.0005, 0.0005, 0.0005 );
  791.                 renderStrokeString( romanFont, "Dog" );
  792.             glPopMatrix();
  793.         }
  794.     glPopMatrix();
  795. }
  796.  
  797. GLvoid
  798. drawScene( GLvoid )
  799. {
  800.     /* local light */
  801.     GLfloat   lightPosition[] = { 0.0, 0.0, 0.0, 1.0 };
  802.  
  803.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  804.  
  805.     glPushMatrix();
  806.  
  807.         /* Move the reference point */
  808.         gluLookAt( 0.0, 0.0, 4.0, xRef, yRef, 0.0, 0.0, 1.0, 0.0 );
  809.  
  810.         /* draw the sun */
  811.         glPushMatrix();
  812.             /* move to the location of the sun */
  813.             glTranslatef( sunPosition, 2.0, -1.5 );
  814.  
  815.             /* use a local light for the sun */
  816.             glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
  817.  
  818.             if ( night ) {
  819.                 glColor3fv( white );
  820.                 glMaterialfv( GL_FRONT, GL_EMISSION, white );
  821.             } else {
  822.                 glColor3fv( yellow );
  823.             }
  824.             glutSolidSphere( 0.2, 8, 15 );
  825.             if ( night ) 
  826.                 glMaterialfv( GL_FRONT, GL_EMISSION, black );
  827.         glPopMatrix();
  828.  
  829.         glPushMatrix();
  830.             glTranslatef( -1.5, 0.0, 0.5 );
  831.             glScalef( 0.7, 0.7, 0.7 );
  832.             drawLamp( GL_LIGHT1 );
  833.         glPopMatrix();
  834.  
  835.         /* draw the ground as a quad mesh so that it will
  836.          * be lit properly
  837.          */
  838.         glPushMatrix();
  839.             glTranslatef( 0.0, -1.0, 0.0 );
  840.             glRotatef( -45.0, 1.0, 0.0, 0.0 );
  841.             glScalef( 3.0, 1.0, 1.0 );
  842.             glCallList( groundList );
  843.         glPopMatrix();
  844.  
  845.         /* draw a sign in the foreground */
  846.         glPushMatrix();
  847.             glTranslatef( -1.5, -1.0, 0.9 );
  848.             glScalef( 0.5, 0.5, 1.0 );
  849.             drawSign();
  850.         glPopMatrix();
  851.  
  852.         /* draw a sign in the background */
  853.         glPushMatrix();
  854.             glTranslatef( 1.0, -1.0, 0.0 );
  855.             drawSign();
  856.         glPopMatrix();
  857.  
  858.         /* draw the house */
  859.         glPushMatrix();
  860.             /* move to where the center of the house should be */
  861.             glTranslatef( -0.5, 0.0, 0.0 );
  862.  
  863.             /* shrink the house slightly */
  864.             glScalef( 0.7, 0.7, 0.7 );
  865.             drawHouse();
  866.  
  867.             /* draw a knocked over trash can next to the house */
  868.             glDisable( GL_CULL_FACE );
  869.             glLightModelf( GL_LIGHT_MODEL_TWO_SIDE, 1.0 ); 
  870.  
  871.             glTranslatef( 0.7, -0.75, 0.5 );
  872.             glRotatef( 90.0, 1.0, 0.0, 0.0 );
  873.             glRotatef( 45.0, 0.0, 0.0, 1.0 );
  874.             glColor3f( 0.0, 0.0, 0.5 ); /* blue */
  875.             SolidCylinder( 0.15, 0.4 );
  876.  
  877.             glLightModelf( GL_LIGHT_MODEL_TWO_SIDE, 0.0 ); 
  878.             glEnable( GL_CULL_FACE );
  879.  
  880.             /* put a label on it */
  881.             glTranslatef( 0.16, 0.2, 0.05 );
  882.             glRotatef( 90.0, 0.0, 1.0, 0.0 );
  883.             glRotatef( -90.0, 0.0, 0.0, 1.0 );
  884.             glScalef( 0.006, 0.006, 0.006 );
  885.             glColor3f( 1.0, 1.0, 1.0 ); /* white */
  886.             render3DString( outlineBase, "Trash" );
  887.         glPopMatrix();
  888.  
  889.         /* draw several tulips in the foreground */
  890.         glPushMatrix();
  891.             glTranslatef( 1.0, -1.0, 1.0 );
  892.             drawFlower( red );
  893.             glTranslatef( 0.0, 0.0, -0.5 );
  894.             drawFlower( yellow );
  895.         glPopMatrix();
  896.         glPushMatrix();
  897.             glTranslatef( -1.0, -1.0, 1.0 );
  898.             drawFlower( blue );
  899.             glTranslatef( 0.0, 0.0, -0.5 );
  900.             drawFlower( magenta );
  901.         glPopMatrix();
  902.  
  903.     glPopMatrix();
  904.  
  905.     checkError( "drawScene" );
  906.     glutSwapBuffers();
  907. }
  908.